#!/usr/bin/env ruby

LKP_SRC = ENV['LKP_SRC'] || File.dirname(File.dirname(File.realpath($PROGRAM_NAME)))

require "#{LKP_SRC}/lib/string_ext"

def largest_bandwidth
  file_size = 0
  bandwidth = 0

  $stdin.each_line do |line|
    break if line.chomp.empty?

    temp_size = line.split(' ')[0].to_f
    temp_bandwidth = line.split(' ')[1].to_f
    if temp_size > file_size
      file_size = temp_size
      bandwidth = temp_bandwidth
    end
  end
  bandwidth
end

def designated_file_size
  designated_hash = {}
  result_str = ''

  $stdin.each_line do |line|
    result_str += line
    break if line =~ /(^\s|^\t)/
  end

  result_str.split("\n").each do |e|
    designated_hash['L1_$'] = e.split[1] if e =~ /^0.00098/
    designated_hash['Main_mem'] = e.split[1] if e =~ /^512.00000/
    designated_hash['Rand_mem'] = e.split[1] if e =~ /^512.00000/
    designated_hash['Mmap_Latency'] = e.split[1] if e =~ /^536.870912/
    designated_hash['L2_$'] = e.split[1] if e =~ /^0.12500/
  end

  designated_hash
end

def read_mb_sec
  bandwidth = 0
  $stdin.each_line do |line|
    break if line.chomp.empty?

    bandwidth = line.split(' ')[1].to_f
  end
  bandwidth
end

null_io_array = []

while (line = $stdin.gets)
  line = line.resolve_invalid_bytes
  case line
  # Extract syscall test result.
  # Simple syscall: 0.2228 microseconds
  # Simple read: 0.3491 microseconds
  # Simple write: 0.2933 microseconds
  # Simple stat: 0.7039 microseconds
  # Simple fstat: 0.3517 microseconds
  # Simple open/close: 1.3696 microseconds
  when /^Simple (\S+): (\d+.\d+) microseconds$/
    null_io_array << $2.to_f if $1.to_s == 'read' || $1.to_s == 'write'
    puts "syscall.#{$1}.latency.us: #{$2}"

  # Extract select test result.
  # Select on 100 fd's: 1.2293 microseconds
  # Select on 100 tcp fd's: 5.0377 microseconds
  when /^Select on 100 fd's: (\d+.\d+) microseconds$/
    puts "Select.100fd.latency.us: #{$1}"
  when /^Select on 100 tcp fd's: (\d+.\d+) microseconds$/
    puts "Select.100tcp.latency.us: #{$1}"

  # Extract Signal test result.
  # Signal handler installation: 0.2315 microseconds
  # Signal handler overhead: 1.1267 microseconds
  when /^Signal handler installation: (\d+.\d+) microseconds/
    puts "sig_inst: #{$1}"
  when /^Signal handler overhead: (\d+.\d+) microseconds/
    puts "sig_hndl: #{$1}"

  # Extract Protection test result.
  # Protection fault: 0.1785 microseconds
  when /^Protection fault: (\d+.\d+) microseconds/
    puts "Prot_Fault: #{$1}"

  # Extract proc test result.
  # Process fork+exit: 134.4530 microseconds
  # Process fork+execve: 382.2759 microseconds
  # Process fork+/bin/sh -c: 918.9524 microseconds
  when /^Process (fork\+\S+)(?:\s-c)?: (\d+.?\d+) microseconds$/
    puts "Process.#{$1}.latency.us: #{$2}"

  # Extract pipe test result.
  # Pipe latency: 7.9239 microseconds
  # Pipe bandwidth: 3042.74 MB/sec
  when /^Pipe latency: (\d+.\d+) \S+$/
    puts "PIPE.latency.us: #{$1}"
  when /^Pipe bandwidth: (\d+.\d+) \S+$/
    puts "PIPE.bandwidth.MB/sec: #{$1}"

  # Extract unix test result.
  # AF_UNIX sock stream latency: 6.2302 microseconds
  # AF_UNIX sock stream bandwidth: 7058.07 MB/sec

  when /^AF_UNIX sock stream latency: (\d+.\d+) \S+$/
    puts "AF_UNIX.sock.stream.latency.us: #{$1}"
  when /^AF_UNIX sock stream bandwidth: (\d+.\d+) \S+$/
    puts "AF_UNIX.sock.stream.bandwidth.MB/sec: #{$1}"

  # Extract ops test results.
  # integer bit: 0.33 nanoseconds
  # integer add: 0.09 nanoseconds
  # integer mul: 0.01 nanoseconds
  # integer div: 7.70 nanoseconds
  # integer mod: 8.12 nanoseconds
  # int64 bit: 0.31 nanoseconds
  # int64 add: 0.08 nanoseconds
  # int64 mul: -0.02 nanoseconds
  when /^(integer|int64|float|double) (bit|add|mul|div|mil): (\d+.\d+) nanoseconds$/
    puts "OPS.#{$1}.#{$2}.latency.ns: #{$3}"

  # Extract UDP test result:
  # UDP latency using localhost: 8.4815 microseconds
  when /^UDP latency using localhost: (\d+.\d+) microseconds$/
    puts "UDP.usinglocalhost.latency.us: #{$1}"

  # For CTX test reuslt, only extract part of data, context switching times for
  # 96p/0K, 96p/16K, 96p/64K (processes/process_size).
  # 2p/0K, 2p/16K, 2p/64K (processes/process_size).
  # 8p/16K, 8p/64K (processes/process_size).
  # 16p/16K, 16p/64K (processes/process_size).
  # "size=0k ovr=0.90
  # 2 1.45
  # 4 1.51
  # 8 1.65
  # 16 1.77
  when /^"size=\d+k ovr=\d+.\d+$/
    size = line.split[0].split('=')[-1].to_i
  when ([0, 16, 64].include? size) && /^96 (\d+.\d+)$/
    puts "CTX.96P.#{size}K.latency.us: #{$1}"
  when ([0, 16, 64].include? size) && /^2 (\d+.\d+)$/
    puts "CTX.2P.#{size}K.latency.us: #{$1}"
  when ([16, 64].include? size) && /^8 (\d+.\d+)$/
    puts "CTX.8P.#{size}K.latency.us: #{$1}"
  when ([16, 64].include? size) && /^16 (\d+.\d+)$/
    puts "CTX.16P.#{size}K.latency.us: #{$1}"

  # Extract FILE test result, get the bandwidth value for the biggest file reading:
  # "read bandwidth
  # 0.000512 489.40
  # 0.001024 900.99
  # 0.002048 1757.11

  when /^"read bandwidth$/
    read_bandwidth = true
    file_size = 0
  when read_bandwidth && /^(\d+.\d+) (\d+.\d+)$/
    if file_size < $1.to_f
      file_size = $1.to_f
      bandwidth = $2
    end
  when read_bandwidth && bandwidth && /^[^\d+]/
    puts "FILE.read.bandwidth.MB/sec: #{bandwidth}"
    read_bandwidth = false

  # Extract TCP test result, get TCP bandwidth value for 64B,10M of message size:
  # TCP latency using localhost: 14.4782 microseconds
  # Socket bandwidth using localhost
  # 0.000001 1.82 MB/sec
  # 0.000064 108.22 MB/sec
  # 0.000128 210.87 MB/sec

  when /^TCP latency using localhost:.+microseconds$/
    puts "TCP.localhost.latency: #{line.split[-2]}"
  when /^Socket bandwidth using localhost$/
    socket_bandwidth = true
  when socket_bandwidth && /^0.000064 (\d+.\d+) MB\/sec$/
    puts "TCP.socket.bandwidth.64B.MB/sec: #{$1}"
  when socket_bandwidth && /^10.485760 (\d+.\d+) MB\/sec$/
    puts "TCP.socket.bandwidth.10MB.MB/sec: #{$1}"

  # Extract CONNECT test result:
  # TCP/IP connection cost to localhost: 19.1327 microseconds
  when /^TCP\/IP connection cost to localhost: (\d+.\d+) microseconds/
    puts "CONNECT.localhost.latency.us: #{$1}"

  # Extract BCOPY test result:
  # bcopy test outputs some test results,but only get the last largest result from the last line.
  # According to lmbench3 source script "getsummary" to extract the four items test result:
  # libc bcopy unaligned, unrolled bcopy unaligned, Memory read bandwidth, Memory write bandwidth.

  # "libc bcopy unaligned"
  # 0.000512 39318.87
  # 0.001024 43561.22
  # 0.002048 48679.99
  # 0.004096 49481.95
  # 0.008192 52732.95
  # ...
  when /^"libc bcopy unaligned$/
    puts "BCOPY.libc.bandwidth.MB/sec: #{largest_bandwidth}"

  # "unrolled bcopy unaligned
  # 0.000512 13442.67
  # 0.001024 13699.91
  # 0.002048 13853.59
  # 0.004096 13955.43
  # 0.008192 13872.00
  # 0.016384 12921.17
  # ...
  when /^"unrolled bcopy unaligned$/
    puts "BCOPY.unrolled.bandwidth.MB/sec: #{largest_bandwidth}"

  # Memory read bandwidth
  # 0.000512 16353.73
  # 0.001024 16577.89
  # 0.002048 16752.28
  # 0.004096 16822.85
  # 0.008192 16834.82
  # ...
  when /^Memory read bandwidth$/
    puts "BCOPY.memory_read.bandwidth.MB/sec: #{largest_bandwidth}"

  # Memory write bandwidth
  # 0.000512 13964.88
  # 0.001024 13954.19
  # 0.002048 13975.07
  # 0.004096 13950.82
  # ...
  when /^Memory write bandwidth$/
    puts "BCOPY.memory_write.bandwidth.MB/sec: #{largest_bandwidth}"

  # Pagefaults on /var/tmp/XXX: 0.2653 microseconds
  when /^Pagefaults on (.*): (.*) microseconds/
    puts "Pagefaults.ms: #{$2}"

  # "Mmap read bandwidth
  # 0.000512 275064.12
  # 0.001024 280518.89
  # 0.002048 293513.60
  # ...
  when /^"Mmap read bandwidth$/
    puts "MMAP.read.bandwidth.MB/sec: #{largest_bandwidth}"

  # "Mmap read open2close bandwidth
  # 0.000512 479.98
  # 0.001024 964.48
  # 0.002048 1931.69
  # ...
  when /^"Mmap read open2close bandwidth$/
    puts "MMAP.read_open2close.bandwidth.MB/sec: #{largest_bandwidth}"

  # Random load latency
  # 416.00000 92.824
  # 448.00000 92.772
  # 512.00000 92.640
  # ...
  when /^Random load latency$/
    result_rand_mem = designated_file_size
    puts "Rand_mem: #{result_rand_mem['Rand_mem']}"

  # "stride=128
  # 416.00000 12.221
  # 448.00000 11.672
  # 480.00000 11.773
  # 512.00000 12.127
  # ...
  when /^"stride=128$/
    result_rand_mem = designated_file_size
    puts "Main_mem: #{result_rand_mem['Main_mem']}"
    puts "L1_$: #{result_rand_mem['L1_$']}"
    puts "L2_$: #{result_rand_mem['L2_$']}"

  # "mappings
  # 67.108864 82
  # 134.217728 151
  # 268.435456 309
  # 536.870912 615
  # ...
  when /^"mappings$/
    result_map = designated_file_size
    puts "Mmap_Latency: #{result_map['Mmap_Latency']}"

  when /bw_mem -P/
    puts "Mem.Bandwidth.MB/sec: #{read_mb_sec}"
  end
end

num = 0
null_io_array.each do |v|
  num += v
end
null_num = format('%.4f', num / 2).to_f
puts "null_io: #{null_num}"
